package cn.bellychang.anemicVsdomain.ddd;

import cn.bellychang.anemicVsdomain.ProductNameEnum;
import cn.bellychang.anemicVsdomain.RecognitionDao;
import org.joda.money.CurrencyUnit;
import org.joda.money.Money;

import java.time.Instant;
import java.util.Date;

/**
 * 在 ddd 中 service 定义了how ，并没有what 是很薄的一层
 * what 委托给了 领域对象来处理
 * 实际上 可以不再抽取Application层的service 直接使用领域层实体对象的业务 {@link com.hfi.anemicVsdomain.ddd.ContractTest}
 * @author ChangLiang
 * @date 2020/5/18
 */
public class RecognitionService {

    private RecognitionDao recognitionDao = new RecognitionDao();

    public void calculateRevenueRecognition(Long contractId) {
        Contract contract = mockDbQuery();
        // contract know how to add a contract's RevenueRecognition
        // contract delegate this to product and product delegate this to RecognitionStrategy
        contract.calculateRecognitions();
    }

    public Money getRecognizedRevenue(Date asOfDate, Long contractId) {
        Money money = Money.zero(CurrencyUnit.of("CNY"));
        try {
            // mock do calculate and save db
            Contract contract = mockDbQuery();
            contract.calculateRecognitions();
            // get RevenueRecognition
            Thread.sleep(1_000);
            money = contract.getRecognizedRevenue(asOfDate);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return money;
    }

    private Contract mockDbQuery() {
        // mock query db and do calculateRevenueRecognition

        // product know calculation strategy
        Product product = new Product(ProductNameEnum.SpreadSheet.name(), new ThreeWayRecognitionStrategy(60, 90));

        // contract know money and signedDate and product
        Contract contract = Contract.builder()
                .id(1L)
                .product(product)
                .revenue(Money.of(CurrencyUnit.of("CNY"), 3000))
                .signedDate(Date.from(Instant.now())).build();

        return contract;
    }
}
